package br.com.hstar.client.quarto;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import br.com.hstar.client.HSTAR;
import br.com.hstar.client.ServiceFactory;
import br.com.hstar.client.TelaPrincipal;
import br.com.hstar.client.cliente.cliente.ClienteUI;
import br.com.hstar.client.formapgto.FormaPgtoUI;
import br.com.hstar.client.quarto.listaprodutos.ListaProdutosPanel;
import br.com.hstar.client.usuario.UsuarioUI;
import br.com.hstar.client.util.ClientSession;
import br.com.hstar.client.util.FormPanel;
import br.com.hstar.client.util.HstarDialogBox;
import br.com.hstar.client.util.HstarUserException;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class QuartoEditPanel extends VerticalPanel {

	private static String MSG_SALVAR = "Deseja realmente salvar as infomações?";
	private static String MSG_ALUGAR = "Deseja realmente alugar o quarto?";
	private static String MSG_FECHAR = "Deseja realmente concluir o aluguel do quarto?";
	private static String MSG_LIMPAR = "Deseja realmente confirmar a limpeza do quarto?";
	
	private FormPanel form;
	private ListaProdutosPanel listaProdPanel;
	private VerticalPanel 	quartoContainer;
	
	private ListBox 	tipoPagamento;
	final ListBox       forPgtoLB = new ListBox(false);
	private ListBox 	formaEntrada;
	private ListBox 	cliente;
	private TextBox 	dataAluguel;
	private TextBox 	horaEntrada;
	private TextBox 	horaSaida;
	private TextArea 	observacao;
	private static TextBox 	valorConsumido;
	private Button		precoQuartoBtn;
	
	private Button 		btnSituacao;
	private Button 		btnSalvar;
	private QuartoUI 	quartoUI;
	private QuartoLabel		quartoLabel;
	
	// Constructors ------------------------------------------------------------------
	public QuartoEditPanel(Integer quartoNumero) {
		form = new FormPanel("Quarto: "+quartoNumero);
		listaProdPanel = new ListaProdutosPanel();
		listaProdPanel.setStyleName("ProdutosIntPanel-Title");
		quartoLabel   = TelaPrincipal.getInstance().getQuartoLabel(quartoNumero);
		//aqui o quartoUI ja deve vir com o ID e NUMERO setado
		quartoUI = quartoLabel.getQuartoUI();
		init();
		
		//adiciona os paineis
		this.add(form);
		this.add(listaProdPanel);
	}
	
	//Methods -------------------------------------------------------------------
	
	private void init() {
		quartoContainer = new VerticalPanel();
		quartoContainer.add(quartoLabel);
		form.addWidget(" ", quartoContainer);

		//dados que aparecerao na tela
		
		HorizontalPanel horPan = new HorizontalPanel();
		tipoPagamento = FormPanel.createListBox(true);
		ServiceFactory.createFormaPgtoService().listAll(new FormaPgtoCallBack());
		forPgtoLB.setVisibleItemCount(3);
		forPgtoLB.setWidth("200px");
		Button removBut = new Button("-");
		removBut.addClickListener(new ClickListener(){
			public void onClick(Widget sender) {
				if(forPgtoLB.getSelectedIndex() != -1)
				forPgtoLB.removeItem(forPgtoLB.getSelectedIndex());
			}			
		});
		tipoPagamento.addChangeListener(new ChangeListener(){
			public void onChange(Widget sender){
				String i = tipoPagamento.getItemText(tipoPagamento.getSelectedIndex());
				if(!i.equals(""))
					forPgtoLB.addItem( tipoPagamento.getItemText(tipoPagamento.getSelectedIndex()), 
							tipoPagamento.getValue(tipoPagamento.getSelectedIndex()) );
			}
		});
		horPan.add(tipoPagamento);
		horPan.add(forPgtoLB);
		horPan.add(removBut);
		FormPanel.addWidget("Tipo de Pagamento", horPan);
		
		formaEntrada   = FormPanel.addListBox("Forma de Entrada", false);
		HSTAR.populateLists(tipoPagamento, formaEntrada);//popula as duas listas acima
		cliente        = FormPanel.addListBox("Cliente", true);
		ServiceFactory.createClienteService().listAll(new ListAllClienteAsyncCallback());
		dataAluguel    = form.addTextBox("Data do Aluguel", 20, 20, "");
		horaEntrada    = form.addTextBox("Hora de Entrada", 20, 20, "");
		horaSaida      = form.addTextBox("Hora de SaÍda", 20, 20, "");
		
		//adiicona um painel horizontal para conter o textbox de preço
		HorizontalPanel hp = form.addHPanel("Total");
		valorConsumido = new TextBox();
		valorConsumido.setMaxLength(20);
		valorConsumido.setVisibleLength(20);
		precoQuartoBtn = new Button("Estadia");
		hp.add(valorConsumido);
		hp.add(precoQuartoBtn);
		
		observacao	   = form.addTextArea("Observação", "250", "150", "");
		
		precoQuartoBtn.addClickListener(new ClickListener(){
			public void onClick(Widget sender) {
				PrecoQuartosDialogBox p = new PrecoQuartosDialogBox(valorConsumido);
				p.show();
			}}
		);
				
		//manipulaçao das datas
		Date date = new Date(currentTimeMillis());
		dataAluguel.setText(HSTAR.convertDateToString(date));
		horaEntrada.setText(date.getHours()+":"+date.getMinutes()+":"+date.getSeconds());
		
		dataAluguel.setEnabled(false);
		horaEntrada.setEnabled(false);
		horaSaida.setEnabled(false);
		valorConsumido.setEnabled(true);
		
		//manipulacao dos botoes de acordo com o estado do quarto
		btnSalvar  = listaProdPanel.addButton("SALVAR");
		if(quartoUI.getSituacao().equals(QuartoUI.LIVRE)) {
			btnSituacao  = listaProdPanel.addButton("ALUGAR");
			btnSalvar.setEnabled(false);
		} else if(quartoUI.getSituacao().equals(QuartoUI.OCUPADO)) {
			btnSituacao  = listaProdPanel.addButton("DESOCUPAR");
		} else {
			btnSituacao  = listaProdPanel.addButton("DISPONÍVEL");
		}
		
		//método usado para atualizar as informações de consumo no quarto
		btnSalvar.addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				if(Window.confirm(MSG_SALVAR)) {
					copyData();
					ServiceFactory.createQuartoService().saveOrUpdate(quartoUI, true, new SaveAsyncCallback());
					//---------------------------------------
					TelaPrincipal.getInstance().refreshGrid();
					RootPanel.get("boxContent").clear();
					RootPanel.get("boxContent").add(TelaPrincipal.getInstance());
				}
			}
		});
		//método usado para mudar a situaçao do quarto
		btnSituacao.addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				String msg;
				if(quartoUI.getSituacao().equals(new Integer(0))) {
					msg = MSG_ALUGAR;						
				} else if(quartoUI.getSituacao().equals(new Integer(1))) {
					msg = MSG_FECHAR;
					quartoUI.setHoraSaida(horaSaida.getText());
				} else {
					msg = MSG_LIMPAR; 
				}
				if(Window.confirm(msg)) {
					copyData();
					quartoLabel.changeState();
					ServiceFactory.createQuartoService().saveOrUpdate(quartoUI, false, new SaveAsyncCallback());
					//---------------------------------------
					TelaPrincipal.getInstance().refreshGrid();
					RootPanel.get("boxContent").clear();
					RootPanel.get("boxContent").add(TelaPrincipal.getInstance());
				}
			}
		});	
		
		
		//metodo que busca se este quarto nao esta sendo usado, ou
		//seja, se o estado deste quarto nao é limpo. caso nao seja, 
		//o quarto deve ser carregado do banco e atualizado.
		ServiceFactory.createQuartoService().retrieveQuartoUsavel(
				quartoUI.getNumero(), new RetrieveQuartoAsyncCallback());
	}

	private void copyData() {
		//quartoUI.setTipoPgto(new Integer(tipoPagamento.getValue(tipoPagamento.getSelectedIndex())));
		ArrayList formaPgtoList = new ArrayList();
		for(int i=0; i < forPgtoLB.getItemCount(); i++)
			formaPgtoList.add(new FormaPgtoUI(forPgtoLB.getValue(i)));
		quartoUI.setFormaspgto(formaPgtoList);
		
		quartoUI.setFormaEntrada(new Integer(formaEntrada.getSelectedIndex()));
		
		if( cliente.getSelectedIndex() != 0 )
		{
			quartoUI.setCliente(new ClienteUI(new Long(cliente.getValue(cliente.getSelectedIndex()))));
		}
		
		//esse codigo tava errado
//		DateTimeFormat sdf = DateTimeFormat.getFormat("MM/dd/yyyy");
//        String s = dataAluguel.getText();
//        String t = sdf.format(sdf.parse(s)); 
		        
		quartoUI.setDataAluguel(dataAluguel.getText());
		quartoUI.setHoraEntrada(horaEntrada.getText());
		quartoUI.setHoraSaida(horaSaida.getText());
		
		if(!valorConsumido.getText().trim().equals(""))
		{
			quartoUI.setValorConsumido(new Double(valorConsumido.getText()));
		}
		quartoUI.setObservacao(observacao.getText());
		quartoUI.setProdutosConsumidos(listaProdPanel.getProdutosSelecionados());
	}
	
	
	
	// callbacks ---------------------------------------------------------------------------------
	private class ListAllClienteAsyncCallback implements AsyncCallback {
		public void onFailure(Throwable caught) {
			Window.alert("ERRO ao listar clientes");
		}
		public void onSuccess(Object result) {
			List clientes = (List) result;
			for (Iterator iter = clientes.iterator(); iter.hasNext();) {
				ClienteUI cliUI = (ClienteUI) iter.next();
				cliente.addItem(cliUI.getNome(), cliUI.getId().toString());				
			}
		}
	}
	
	private class RetrieveQuartoAsyncCallback implements AsyncCallback {
		public void onFailure(Throwable caught) {
			Window.alert("ERRO ao listar quarto");
		}
		public void onSuccess(Object result) {
			QuartoUI qUI = (QuartoUI) result;
			if(qUI != null) {
				
				//sets the cliente
				if(qUI.getCliente() != null) {
					for(int i = 0; i < cliente.getItemCount(); i++) {
						if(cliente.getItemText(i).equals(qUI.getCliente().getValue(1))) {
							cliente.setSelectedIndex(i);
							break;
						}
					}
				}

				if(qUI.getFormaspgto() != null){
					for(int i=0;i<qUI.getFormaspgto().size(); i++)
						forPgtoLB.addItem(
								((FormaPgtoUI)qUI.getFormaspgto().get(i)).getDescricao(),
								((FormaPgtoUI)qUI.getFormaspgto().get(i)).getId().toString());
				}
				
				dataAluguel.setText(qUI.getDataAluguel());
				horaEntrada.setText(qUI.getHoraEntrada());
				
				quartoUI.setId(qUI.getId());
				observacao.setText(qUI.getObservacao());
				formaEntrada.setSelectedIndex(qUI.getFormaEntrada().intValue());
				listaProdPanel.setProdutosSelecionados(new HashSet(qUI.getProdutosConsumidos()));
				valorConsumido.setText((qUI.getValorConsumido() == null)?"":qUI.getValorConsumido().toString());
				
				//caso o usuario logado seja a camareira, desabilita o botao de salvar e
				//deixa a penas o de mudar a situacao do quarto.
				UsuarioUI usu = (UsuarioUI)ClientSession.getInstance().getProperty("usuario");
				
				int usuPermissao = usu.getPermissao().intValue();
				int camareira = new Integer(UsuarioUI.CAMAREIRA).intValue();
				int quartoSituacao = quartoUI.getSituacao().intValue();
				int quartoSujo = QuartoUI.SUJO.intValue();
				
				if(usu != null && usuPermissao == camareira) {
					btnSalvar.setVisible(false);
					//o estado do quarto deve ser SUJO para que a camareira limpe
					//e coloque o quarto como LIVRE novamente. Caso nao seja este
					//o estado do quarto, o botao de mudar estado nao aprecerá.
					if(quartoSituacao != quartoSujo)
						btnSituacao.setVisible(false);
				}
			}
		}
	}
	
	private class SaveAsyncCallback implements AsyncCallback {
		public void onFailure(Throwable caught) {
			if(caught instanceof HstarUserException)
			{					
				new HstarDialogBox("Quarto",caught.getMessage());
			}
		}
		public void onSuccess(Object result) {
			//volta para a tela principal
			TelaPrincipal.getInstance().refreshGrid();
			RootPanel.get("boxContent").clear();
			RootPanel.get("boxContent").add(TelaPrincipal.getInstance());
		}
	}
	
	private class FormaPgtoCallBack  implements AsyncCallback {
		public void onFailure(Throwable caught) {
			if(caught instanceof HstarUserException)
			{					
				new HstarDialogBox("Formas de Pagamento",caught.getMessage());
			}
		}
		public void onSuccess(Object result) {
			ArrayList formaspgt = (ArrayList)result;
			for(int i = 0; i < formaspgt.size(); i++) {
				tipoPagamento.addItem( ((FormaPgtoUI)formaspgt.get(i)).getDescricao(),
						((FormaPgtoUI)formaspgt.get(i)).getId().toString());
			}
		}
	}
	
	public static void setValorConsumido(String valor) {
		valorConsumido.setText(valor);
	}
	
	//Funcoes relacionadas a hora
	//---------------------------------------------------------------------------------------------
	public static native long currentTimeMillis() /*-{
    return (new Date()).getTime();
  	}-*/;
	
	/**
	 * Converts time in seconds to a <code>String</code> in the format HH:mm:ss.
	 * @param time the time in seconds.
	 * @return a <code>String</code> representing the time in the format HH:mm:ss.
	 */
	public static String secondsToString(long time)	{
	    int seconds = (int)(time % 60);
	    int minutes = (int)((time/60) % 60);
	    int hours = (int)((time/3600) % 24);
	    String secondsStr = (seconds<10 ? "0" : "")+seconds;
	    String minutesStr = (minutes<10 ? "0" : "")+minutes;
	    String hoursStr = (hours<10 ? "0" : "")+hours;
	    return new String(hoursStr+":"+minutesStr+":"+secondsStr);
	}
	 
	/**
	 * Converts time in milliseconds to a <code>String</code> in the format HH:mm:ss.SSS.
	 * @param time the time in milliseconds.
	 * @return a <code>String</code> representing the time in the format HH:mm:ss.SSS.
	 */
	public static String millisecondsToString(long time) {
	    int milliseconds = (int)(time % 1000);
	    int seconds = (int)((time/1000) % 60);
	    int minutes = (int)((time/60000) % 60);
	    int hours = (int)((time/3600000) % 24);
	    String millisecondsStr = (milliseconds<10 ? "00" : (milliseconds<100 ? "0" : ""))+milliseconds;
	    String secondsStr = (seconds<10 ? "0" : "")+seconds;
	    String minutesStr = (minutes<10 ? "0" : "")+minutes;
	    String hoursStr = (hours<10 ? "0" : "")+hours;
	    return new String(hoursStr+":"+minutesStr+":"+secondsStr+"."+millisecondsStr);
	}
}      